原始题目:剑指 Offer 65. 不用加减乘除做加法 (opens new window)
解题思路:
本题考察的是通过位运算来做加法。
加法需要考虑进位,在位运算里,进位可以通过左移然后加回无进位和中。
假设有两个数的二进制形式 和 。其和 。对于第 位来说,) 和 相加可能有以下的结果。
无进位和 | 进位 | ||
---|---|---|---|
观察可以看出, 是 和 异或的结果,而 是 和 与运算然后左移一位的结果。
因此,求 的过程转化成求 和 的无进位和 以及进位 的过程,然后将 补还给 。补还之后,可能会产生新的进位,因此需要循环处理,直到进位为 。
这个过程同样适合与 或者 为负数的时候,因为正数负数都是用补码存储的。
代码:
public int add(int a, int b) {
while (b != 0) {
// 求进位
int c = (a & b) << 1;
// 不考虑进位,结果赋值给 a
a = a ^ b;
// 如果存在进位,则 b != 0,那么在下一个循环中,
// 就会将进位和 a 相加,直到进位为 0
b = c;
}
return a;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
复杂度分析
- 时间复杂度:最差情况下(例如 =
0x7fffffff
, 时),需循环 次,使用 时间;每轮中的常数次位操作使用 时间。 - 空间复杂度:辅助变量占用常数大小的空间。